package com.example.demo.use_demo.a_excel_demo.entity;

import cn.hutool.core.util.StrUtil;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 验证
 * [1] 必需字段
 * [2] 字段数据类型（缺省情况下，所有 HTTP 请求参数都是“字符串”）
 * [3] 字段长度
 * [4] 字段范围
 * [5] 字段选项
 * [6] 字段模式 正则的特殊规则
 * [7] cookie 值
 * [8] HTTP 响应
 * @author farben
 */
public class Validator {

    /**
     * 验证数字字段（int 类型）<br>
     * <textarea rows="6" cols="88">
     * //	check	if	the	HTTP	request	parameter	is	of	type	int
     * String	fieldValue	=	request.getParameter("fieldName");
     * if	(Validator.validateInt(fieldValue))	{
     * //	fieldValue	is	valid,	continue	processing	request
     * ...
     * }
     * </textarea>
     *
     */
    public static boolean validateInt(String value) {
        boolean isFieldValid = false;
        try {
            int intValue = Integer.parseInt(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * 验证byte
     *
     */
    public static boolean validateByte(String value) {
        boolean isFieldValid = false;
        try {
            byte byteValue = Byte.parseByte(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * 验证Short
     */
    public static boolean validateShort(String value) {
        boolean isFieldValid = false;
        try {
            short shortValue = Short.parseShort(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * 验证Long
     *
     */
    public static boolean validateLong(String value) {
        boolean isFieldValid = false;
        try {
            long longValue = Long.parseLong(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * 验证Float
     *
     */
    public static boolean validateFloat(String value) {
        boolean isFieldValid = false;
        try {
            Float.parseFloat(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * 验证Double
     *
     */
    public static boolean validateDouble(String value) {
        boolean isFieldValid = false;
        try {
            Double.parseDouble(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * 验证Double
     */
    public static boolean validateBigDecimal(String value) {
        boolean isFieldValid = false;
        try {
            new BigDecimal(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }


    /**
     * 验证Double
     *
     */
    public static boolean validateBigDecimals(String... value) {
        for (String s : value) {
            if (!validateBigDecimal(s)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 验证Date
     *
     */
    public static boolean validateDate(String value) {
        boolean isFieldValid = false;
        // 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写；
        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm");
        try {
            // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            format.parse(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * 验证Date
     *
     */
    public static boolean validateDate(String value, String format) {
        boolean isFieldValid = false;
        // 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写；
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            sdf.setLenient(false);
            sdf.parse(value);
            isFieldValid = true;
        } catch (Exception ignored) {
        }
        return isFieldValid;
    }

    /**
     * [3] 字段长度“始终”确保输入参数（HTTP 请求参数或 cookie 值）有最小长度和/或最大长度的限制。<br>
     * <textarea rows="6" cols="88">
     * String	userName	=	request.getParameter("userName");
     * if	(Validator.validateRequired(userName))	{
     * if	(Validator.validateLength(userName,	8,	20))	{
     * //	userName	is	valid,	continue	further	processing
     * ...
     * }
     * }
     * </textarea>
     */
    public static boolean validateLength(String value, int minLength, int maxLength) {
        if (StrUtil.isBlank(value)) {
            value = "";
        }
        return (value.length() >= minLength && value.length() <= maxLength);
    }

    /**
     * [5] 字段选项 Web 应用程序通常会为用户显示一组可供选择的选项
     * <textarea rows="6" cols="88">
     * //	Allowed	options
     * String[]	options	=	{"option1",	"option2",	"option3");
     * //	Verify	that	the	user	selection	is	one	of	the	allowed	options
     * String	userSelection	=	request.getParameter("userSelection");
     * if	(Validator.validateOption(options,	userSelection))	{
     * //	valid	user	selection,	continue	processing	request
     * ...
     * }
     * </textarea>
     *
     */
    public static boolean validateOption(Object[] options, Object value) {
        boolean isValidValue = false;
        try {
            List list = Arrays.asList(options);
            isValidValue = list.contains(value);
        } catch (Exception ignored) {
        }
        return isValidValue;
    }

    /**
     * [6] 字段模式始终检查用户输入与由功能需求定义的模式是否匹配<br>
     * 例如，如果 userName 字段应仅允许字母数字字符，且不区分
     * 大小写，那么请使用以下正则表达式：^[a-zA-Z0-9]*$<br>
     * <textarea rows="6" cols="88">
     * String	userName	=	request.getParameter("userName");
     * if	(Validator.matchPattern(userName,	"^[a-zA-Z0-9]*$"))	{
     * //	userName	is	valid,	continue	processing	request
     * ...
     * }
     * </textarea>
     */
    public static boolean matchPattern(String value, String expression) {
        boolean match = false;
        if (StrUtil.isNotBlank(expression)) {
            Pattern pattern = Pattern.compile(expression);
            match = pattern.matcher(value).matches();
        }
        return match;
    }

    /**
     * 验证cookie
     *
     */
    public static boolean validateCookie(HttpServletRequest request) {
        boolean match = false;
        //	Example	to	validate	a	required	cookie	value
        //	First	retrieve	all	available	cookies	submitted	in	the	HTTP	request
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            //	find	the	"user"	cookie
            for (Cookie cookie : cookies) {
                if ("user".equals(cookie.getName())) {
                    //	validate	the	cookie	value
                    if (StrUtil.isNotBlank(cookie.getValue())) {
                        //	valid	cookie	value,	continue	processing	request

                    }
                }
            }
        }
        return match;
    }

    /**
     * [8] HTTP 响应
     * [8-1] 过滤用户输入要保护应用程序免遭跨站点脚本编制的攻击，
     * 请通过将敏感字符转换为其对应的字符实体来清理HTML。
     * 这些是 HTML 敏感字符：< > " ' % ; ) ( &
     */
    public static String filter(String value) {
        if (value == null) {
            return null;
        }
        StringBuilder result = new StringBuilder(value.length());
        for (int i = 0; i < value.length(); ++i) {
            switch (value.charAt(i)) {
                case '<':
                    result.append("&lt;");
                    break;
                case '>':
                    result.append("&gt;");
                    break;
                case '"':
                    result.append("&quot;");
                    break;
                case '\'':
                    result.append("&#39;");
                    break;
                case '%':
                    result.append("&#37;");
                    break;
                case ';':
                    result.append("&#59;");
                    break;
                case '(':
                    result.append("&#40;");
                    break;
                case ')':
                    result.append("&#41;");
                    break;
                case '&':
                    result.append("&amp;");
                    break;
                case '+':
                    result.append("&#43;");
                    break;
                default:
                    result.append(value.charAt(i));
                    break;
            }
        }
        return result.toString();
    }
}

